﻿#region

using System.Collections.Concurrent;
using FreeRedis;
using Microsoft.Extensions.Configuration;
using Vin.Extension.Redis.Models;
using Vin.Tool.AspNetCore.Singleton;

#endregion

namespace Vin.Extension.Redis.Cache;

public static class RedisCacheManager
{
    /// <summary>
    /// key:数据库索引
    /// </summary>
    private static readonly ConcurrentDictionary<int, RedisCache> RedisCacheDict = new();

    private static RedisOption? _redisOption;

    static RedisCacheManager()
    {
        var defaultConnectString = VinApp.Configuration.GetSection(VinRedisExtension.OptionKey).Value;
        if (!string.IsNullOrEmpty(defaultConnectString))
        {
            RedisCacheDict.TryAdd(0, new RedisCache(defaultConnectString));
        }
        else
        {
            var redisOptions = VinApp.Configuration.GetSection(VinRedisExtension.OptionKey).Get<RedisOption>();
            if (redisOptions == null)
            {
                throw new Exception("RedisServer初始化失败，未找到配置，请检查app settings.json是否用Cache:Redis节点");
            }

            _redisOption = redisOptions;
            RedisCacheDict.TryAdd(_redisOption.DefaultDb, new RedisCache(
                GetConnectionStringBuilder(_redisOption, _redisOption.DefaultDb),
                _redisOption.NodeOptions.Select(item => GetConnectionStringBuilder(item, _redisOption.DefaultDb))
                    .ToArray()));

            // InitRedisCache(redisOptions);
        }
    }

    /// <summary>
    /// 获取连接字符串
    /// </summary>
    /// <param name="option"></param>
    /// <param name="db"></param>
    /// <returns></returns>
    private static ConnectionStringBuilder GetConnectionStringBuilder(RedisOption option, int db)
    {
        var connectStrList = new List<string>()
        {
            $"{option.Host}:{option.Port}",
            $"user={option.User}",
            $"password={option.Password}",
            $"ssl={option.Ssl}",
            $"prefix={option.Prefix}",
            $"defaultDatabase={db}"
        };

        if (!string.IsNullOrEmpty(option.OtherString))
        {
            connectStrList.Add(option.OtherString);
        }

        return string.Join(',', connectStrList);
    }

    // /// <summary>
    // /// 初始化Redis缓存
    // /// </summary>
    // /// <param name="option"></param>
    // private static void InitRedisCache(RedisOption option)
    // {
    //     // 127.0.0.1[:6379],password=123456,defaultDatabase=13,poolsize=50,ssl=false,writeBuffer=10240,prefix=key前辍
    //     foreach (var db in option.Dbs?.Distinct() ?? new List<int>() { 0, option.DefaultDb })
    //     {
    //         if (RedisCacheDict.ContainsKey(db)) continue;
    //         // RedisCacheDict.Add(db,
    //         //     new RedisCache(new RedisClient(GetConnectionStringBuilder(option, db),
    //         //         option.NodeOptions.Select(item => GetConnectionStringBuilder(item, db)).ToArray())));
    //         RedisCacheDict.Add(db,
    //             new RedisCache(GetConnectionStringBuilder(option, db),
    //                 option.NodeOptions.Select(item => GetConnectionStringBuilder(item, db)).ToArray()));
    //     }
    // }

    /// <summary>
    /// 获取Redis缓存
    /// </summary>
    /// <param name="db"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static RedisCache GetRedisCache(int db = 0)
    {
        if (RedisCacheDict.TryGetValue(db, out var cache))
        {
            return cache;
        }

        if (_redisOption == null) throw new Exception("未找到Redis配置");

        var cacheConn = new RedisCache(GetConnectionStringBuilder(_redisOption, db),
            _redisOption.NodeOptions.Select(item => GetConnectionStringBuilder(item, db)).ToArray());
        RedisCacheDict.TryAdd(db, cacheConn);
        return cacheConn;
    }

    /// <summary>
    /// 获取Redis客户端
    /// </summary>
    /// <param name="db"></param>
    /// <returns></returns>
    public static IRedisClient GetRedisClient(int db = 0)
    {
        return GetRedisCache(db).RedisClient;
    }
}